// file: include/driver/ide.h
// autor: jiangxinpeng
// time: 2021.3.24
// copyright: (C) by jiangxinpeng,All right are reserved.

#ifndef DRIVER_IDE_H
#define DRIVER_IDE_H

#include <os/driver.h>
#include <lib/type.h>

// device name
#define DEVICE_NAME "hd"

// driver name and version
#define DRIVER_NAME "ide_driver"
#define DRIVER_VER "0.1"

// ide disk max open number
#define IDE_DISK_MAX 4

// define channel
#define ATA_PRIMARY_CHANNEL 0x0
#define ATA_SLAVE_CHANNEL 0x01

// define device type
#define ATA_DEVICE 0x00
#define ATAPI_DEVICE 0x01

// define device sel
#define ATA_MASTER_DEVICE 0x00
#define ATA_SLAVE_DEVICE 0x01

// ide opeartor
#define IDE_READ 0
#define IDE_WRITE 1

// device register mask bits
#define DEV_MBS 0xA0 // bits 7 and 5 are set to 1

// make ATA device register mask
#define ATA_DEVICE_MASK(mode, sel, head) ((DEV_MBS) | (mode) << 6 | (sel) << 4 | (head)&0xF)

// define ata device command and  register io address
#define ATA_PRIMARY_CMDREG_BA 0x1f0
#define ATA_PRIMARY_ALTREG_BA 0x3f6
#define ATA_SLAVE_CMDREG_BA 0x170
#define ATA_SLAVE_ALTREG_BA 0x376
#define ATA_DMA_BA 0x0

// define ata command reg group
// ata data reg
#define ATA_REG_DATA 0x00
// ata error reg
#define ATA_REG_ERR 0x01
// ata feature reg
#define ATA_REG_FEATURE 0x01
// ata sector count0 reg
#define ATA_REG_SECCNT0 0x02
// ata group lba address0 reg
#define ATA_REG_LBA0 0x03
// ata lba address1 reg
#define ATA_REG_LBA1 0x04
// ata lba address2 reg
#define ATA_REG_LBA2 0x05
// ata sel reg
#define ATA_REG_HDDSEL 0x06
// ata command regm
#define ATA_REG_CMD 0x07
// ata status reg
#define ATA_REG_STATUS 0x07
// ata sector count1 reg
#define ATA_REG_SECCNT1 0x08
// ata lba3 address reg
#define ATA_REG_LBA3 0x03
// ata lba4 address reg
#define ATA_REG_LBA4 0x04
// ata lba5 address reg
#define ATA_REG_LBA5 0x05

// ata alternate status reg
#define ATA_REG_ALTSTU 0x0C
// ata control group control reg
#define ATA_REG_CTRL 0x0C

// ata control device address reg,unuse
#define ATA_REG_DRVAD_REG 0x0D
// ata bus ide dma0
#define ATA_REG_BUSIDEDMA0_REG 0x0E

// ata bus ide dma1
#define ATA_REG_BUSIDEDMA1_REG 0x0F
// ata bus ide dma2
#define ATA_REG_BUSIDEDMA2_REG 0x10
// ata bus ide dma3
#define ATA_REG_BUSIDEDMA3_REG 0x11
// ata bus ide dma4
#define ATA_REG_BUSIDEDMA4_REG 0x12
// ata bus ide dma5
#define ATA_REG_BUSIDEDMA5_REG 0x13
// ata bus ide dma6
#define ATA_REG_BUSIDEDMA6_REG 0x14
// ata bus ide dma7
#define ATA_REG_BUSIDEDMA7_REG 0x15

// define ata status
// Busy
#define ATA_STATUS_BUSY 0x80
// Drive ready
#define ATA_STATUS_READY 0x40
// Drive write fault
#define ATA_STATUS_DEVFAULT 0x20
// Drive seek complete
#define ATA_STATUS_DSC 0x10
// Data request ready
#define ATA_STATUS_DRQ 0x08
// Corrected data
#define ATA_STATUS_CORR 0x04
// Index
#define ATA_STATUS_IDX 0x02
// Error
#define ATA_STATUS_ERR 0x01

// define error reg filed
//  Bad block
#define ATA_ER_BBK 0x80
// Uncorrectable data
#define ATA_ER_UNC 0x40
// Media changed
#define ATA_ER_MC 0x20
// ID mark not found
#define ATA_ER_IDNF 0x10
// Media change request
#define ATA_ER_MCR 0x08
// Command aborted
#define ATA_ER_ABRT 0x04
// Track 0 not found
#define ATA_ER_TK0NF 0x02
// No address mark
#define ATA_ER_AMNF 0x01

// define command
// When you write to the Command/Status port, you are executing one of the commands below
#define ATA_CMD_DRIVERCHECK 0x90
#define ATA_CMD_SECTORCHECK 0x40
#define ATA_CMD_READ_PIO 0x20
#define ATA_CMD_READ_PIO_EXT 0x24
#define ATA_CMD_READ_DMA 0xC8
#define ATA_CMD_READ_DMA_EXT 0x25
#define ATA_CMD_WRITE_PIO 0x30
#define ATA_CMD_WRITE_PIO_EXT 0x34
#define ATA_CMD_WRITE_DMA 0xCA
#define ATA_CMD_WRITE_DMA_EXT 0x35
#define ATA_CMD_CACHE_FLUSH 0xE7
#define ATA_CMD_CACHE_FLUSH_EXT 0xEA
#define ATA_CMD_PACKET 0xA0`````````
#define ATA_CMD_IDENTIFY_PACKET 0xA1
#define ATA_CMD_IDENTIFY 0xEC

#define ATAPI_CMD_EJECT 0x1B
#define ATAPI_CMD_READ 0xA8

// device control
#define ATA_CONTROL_IEN 0x1
#define ATA_CONTROL_SRST 0x2

// disk type
#define DISK_MBR 0
#define DISK_GPT 1
#define DISK_NONE 2

// ide disk count addr
#define IDE_DISK_NUM (PAGE_HIGH_BASE + 0x0475)

typedef struct _device_extension device_extension_t;

// lba address bag format
union bag
{
    // used to lba28
    struct
    {
        uint8_t lba0;
        uint8_t lba1;
        uint8_t lba2;
        uint8_t lba3;
    } lba28;
    // used to lba48
    struct
    {
        uint8_t lba0;
        uint8_t lba1;
        uint8_t lba2;
        uint8_t lba3;
        uint8_t lba4;
        uint8_t lba5;
    } lba48;
} lbabag;

// define channel info
typedef struct ide_channel
{
    uint16_t iobase;     // io base
    uint16_t ctrlbase;   // control base
    uint16_t bmasteride; // bus master ide
    uint8_t irqno;       // irq number
    uint8_t curop;       // current operator
    uint8_t curactive;   // active in master or slave
    device_extension_t *extension;
} ide_channel_t;

struct ide_identy
{
    //	0	General configuration bit-significant information
    unsigned short General_Config;

    //	1	Obsolete
    unsigned short Obsolete0;

    //	2	Specific configuration
    unsigned short Specific_Coinfig;

    //	3	Obsolete
    unsigned short Obsolete1;

    //	4-5	Retired
    unsigned short Retired0[2];

    //	6	Obsolete
    unsigned short Obsolete2;

    //	7-8	Reserved for the CompactFlash Association
    unsigned short CompactFlash[2];

    //	9	Retired
    unsigned short Retired1;

    //	10-19	Serial number (20 ASCII characters)
    unsigned short Serial_Number[10];

    //	20-21	Retired
    unsigned short Retired2[2];

    //	22	Obsolete
    unsigned short Obsolete3;

    //	23-26	Firmware revision(8 ASCII characters)
    unsigned short Firmware_Version[4];

    //	27-46	Model number (40 ASCII characters)
    unsigned short Model_Number[20];

    //	47	15:8 	80h
    //		7:0  	00h=Reserved
    //			01h-FFh = Maximumnumber of logical sectors that shall be transferred per DRQ data block on READ/WRITE MULTIPLE commands
    unsigned short Max_logical_transferred_per_DRQ;

    //	48	Trusted Computing feature set options
    unsigned short Trusted_Computing_feature_set_options;

    //	49	Capabilities
    unsigned short Capabilities0;

    //	50	Capabilities
    unsigned short Capabilities1;

    //	51-52	Obsolete
    unsigned short Obsolete4[2];

    //	53	15:8	Free-fall Control Sensitivity
    //		7:3 	Reserved
    //		2 	the fields reported in word 88 are valid
    //		1 	the fields reported in words (70:64) are valid
    unsigned short Report_88_70to64_valid;

    //	54-58	Obsolete
    unsigned short Obsolete5[5];

    //	59	15:9	Reserved
    //		8	Multiple sector setting is valid
    //		7:0	xxh current setting for number of logical sectors that shall be transferred per DRQ data block on READ/WRITE Multiple commands
    unsigned short Mul_Sec_Setting_Valid;

    //	60-61	Total number of user addresssable logical sectors for 28bit CMD
    unsigned short lba28Sectors[2];

    //	62	Obsolete
    unsigned short Obsolete6;

    //	63	15:11	Reserved
    //		10:8=1 	Multiword DMA mode 210 is selected
    //		7:3 	Reserved
    //		2:0=1 	Multiword DMA mode 210 and below are supported
    unsigned short MultWord_DMA_Select;

    //	64	15:8	Reserved
    //		7:0	PIO mdoes supported
    unsigned short PIO_mode_supported;

    //	65	Minimum Multiword DMA transfer cycle time per word
    unsigned short Min_MulWord_DMA_cycle_time_per_word;

    //	66	Manufacturer`s recommended Multiword DMA transfer cycle time
    unsigned short Manufacture_Recommend_MulWord_DMA_cycle_time;

    //	67	Minimum PIO transfer cycle time without flow control
    unsigned short Min_PIO_cycle_time_Flow_Control;

    //	68	Minimum PIO transfer cycle time with IORDY flow control
    unsigned short Min_PIO_cycle_time_IOREDY_Flow_Control;

    //	69-70	Reserved
    unsigned short Reserved1[2];

    //	71-74	Reserved for the IDENTIFY PACKET DEVICE command
    unsigned short Reserved2[4];

    //	75	Queue depth
    unsigned short Queue_depth;

    //	76	Serial ATA Capabilities
    unsigned short SATA_Capabilities;

    //	77	Reserved for Serial ATA
    unsigned short Reserved3;

    //	78	Serial ATA features Supported
    unsigned short SATA_features_Supported;

    //	79	Serial ATA features enabled
    unsigned short SATA_features_enabled;

    //	80	Major Version number
    unsigned short Major_Version;

    //	81	Minor version number
    unsigned short Minor_Version;

    //	82	Commands and feature sets supported
    unsigned short cmdSet0;

    //	83	Commands and feature sets supported
    unsigned short cmdSet1;

    //	84	Commands and feature sets supported
    unsigned short Cmd_feature_sets_supported2;

    //	85	Commands and feature sets supported or enabled
    unsigned short Cmd_feature_sets_supported3;

    //	86	Commands and feature sets supported or enabled
    unsigned short Cmd_feature_sets_supported4;

    //	87	Commands and feature sets supported or enabled
    unsigned short Cmd_feature_sets_supported5;

    //	88	15 	Reserved
    //		14:8=1 	Ultra DMA mode 6543210 is selected
    //		7 	Reserved
    //		6:0=1 	Ultra DMA mode 6543210 and below are suported
    unsigned short Ultra_DMA_modes;

    //	89	Time required for Normal Erase mode SECURITY ERASE UNIT command
    unsigned short Time_required_Erase_CMD;

    //	90	Time required for an Enhanced Erase mode SECURITY ERASE UNIT command
    unsigned short Time_required_Enhanced_CMD;

    //	91	Current APM level value
    unsigned short Current_APM_level_Value;

    //	92	Master Password Identifier
    unsigned short Master_Password_Identifier;

    //	93	Hardware resset result.The contents of bits (12:0) of this word shall change only during the execution of a hardware reset.
    unsigned short HardWare_Reset_Result;

    //	94	Current AAM value
    //		15:8 	Vendor’s recommended AAM value
    //		7:0 	Current AAM value
    unsigned short Current_AAM_value;

    //	95	Stream Minimum Request Size
    unsigned short Stream_Min_Request_Size;

    //	96	Streaming Transger Time-DMA
    unsigned short Streaming_Transger_time_DMA;

    //	97	Streaming Access Latency-DMA and PIO
    unsigned short Streaming_Access_Latency_DMA_PIO;

    //	98-99	Streaming Performance Granularity (DWord)
    unsigned short Streaming_Performance_Granularity[2];

    //	100-103	Total Number of User Addressable Logical Sectors for 48-bit commands (QWord)
    unsigned short lba48Sectors[4];

    //	104	Streaming Transger Time-PIO
    unsigned short Streaming_Transfer_Time_PIO;

    //	105	Reserved
    unsigned short Reserved4;

    //	106	Physical Sector size/Logical Sector Size
    unsigned short Physical_Logical_Sector_Size;

    //	107	Inter-seek delay for ISO-7779 acoustic testing in microseconds
    unsigned short Inter_seek_delay;

    //	108-111	World wide name
    unsigned short World_wide_name[4];

    //	112-115	Reserved
    unsigned short Reserved5[4];

    //	116	Reserved for TLC
    unsigned short Reserved6;

    //	117-118	Logical sector size (DWord)
    unsigned short Words_per_Logical_Sector[2];

    //	119	Commands and feature sets supported (Continued from words 84:82)
    unsigned short CMD_feature_Supported;

    //	120	Commands and feature sets supported or enabled (Continued from words 87:85)
    unsigned short CMD_feature_Supported_enabled;

    //	121-126	Reserved for expanded supported and enabled settings
    unsigned short Reserved7[6];

    //	127	Obsolete
    unsigned short Obsolete7;

    //	128	Security status
    unsigned short Security_Status;

    //	129-159	Vendor specific
    unsigned short Vendor_Specific[31];

    //	160	CFA power mode
    unsigned short CFA_Power_mode;

    //	161-167	Reserved for the CompactFlash Association
    unsigned short Reserved8[7];

    //	168	Device Nominal Form Factor
    unsigned short Dev_from_Factor;

    //	169-175	Reserved
    unsigned short Reserved9[7];

    //	176-205	Current media serial number (ATA string)
    unsigned short Current_Media_Serial_Number[30];

    //	206	SCT Command Transport
    unsigned short SCT_Cmd_Transport;

    //	207-208	Reserved for CE-ATA
    unsigned short Reserved10[2];

    //	209	Alignment of logical blocks within a physical block
    unsigned short Alignment_Logical_blocks_within_a_physical_block;

    //	210-211	Write-Read-Verify Sector Count Mode 3 (DWord)
    unsigned short Write_Read_Verify_Sector_Count_Mode_3[2];

    //	212-213	Write-Read-Verify Sector Count Mode 2 (DWord)
    unsigned short Write_Read_Verify_Sector_Count_Mode_2[2];

    //	214	NV Cache Capabilities
    unsigned short NV_Cache_Capabilities;

    //	215-216	NV Cache Size in Logical Blocks (DWord)
    unsigned short NV_Cache_Size[2];

    //	217	Nominal media rotation rate
    unsigned short Nominal_media_rotation_rate;

    //	218	Reserved
    unsigned short Reserved11;

    //	219	NV Cache Options
    unsigned short NV_Cache_Options;

    //	220	Write-Read-Verify feature set current mode
    unsigned short Write_Read_Verify_feature_set_current_mode;

    //	221	Reserved
    unsigned short Reserved12;

    //	222	Transport major version number.
    //		0000h or ffffh = device does not report version
    unsigned short Transport_Major_Version_Number;

    //	223	Transport Minor version number
    unsigned short Transport_Minor_Version_Number;

    //	224-233	Reserved for CE-ATA
    unsigned short Reserved13[10];

    //	234	Minimum number of 512-byte data blocks per DOWNLOAD MICROCODE command for mode 03h
    unsigned short Mini_blocks_per_CMD;

    //	235	Maximum number of 512-byte data blocks per DOWNLOAD MICROCODE command for mode 03h
    unsigned short Max_blocks_per_CMD;

    //	236-254	Reserved
    unsigned short Reserved14[19];

    //	255	Integrity word
    //		15:8	Checksum
    //		7:0	Checksum Validity Indicator
    unsigned short Integrity_word;
} __attribute__((packed));

typedef struct ide_identy ide_info_t;

typedef struct _device_extension
{
    device_object_t *device_object; // device object
    ide_channel_t *channel;         // device channel
    int disk_type;                  // disk type (MBR or GPT)
    ide_info_t *info;               // disk info
    char model[40];                 // model (pyhichs driver name)
    uint32_t exist;                 // disk exits
    uint32_t driver;                // drive (master or slave disk)
    uint32_t type;                  // device type (ATA  or ATAP)
    uint8_t signature;              // drive signature
    uint32_t capabilities;          // features
    uint32_t command_sets;          // command sets support
    uint32_t size;                  // sizes of sector

    uint64_t rwoff; // drive read/write offset
    // status info
    uint32_t read_sectors;  // read sector counts
    uint32_t write_sectors; // write sector counts

    device_object_t *vol[128]; // vol device object
} device_extension_t;

typedef struct
{
    string_t device_name;           // device name
    device_object_t *device_object; // device object;
    device_object_t *disk_object;   // disk object

    uint32_t size;      // volume size
    uint64_t start_lba; // volume start lba

    uint64_t rwoff; // read/write offset
    // status info
    uint32_t read_sectors;  // read sectors
    uint32_t write_sectors; // write sector size
} vol_extension_t;

ide_channel_t channelinfo[2];

#endif